﻿using System;
using System.Windows.Input; // 引入 WPF 命令相关接口和管理类

namespace WPFServices.Commands // 命令类的命名空间
{
    // RelayCommand 类：非泛型命令，用于不带参数的或参数类型为 object 的命令。
    // 实现了 ICommand 接口，用于连接 UI (View) 和逻辑 (ViewModel)。
    public class RelayCommand : ICommand
    {
        // _execute: 命令执行时调用的操作。
        private readonly Action<object> _execute;
        // _canExecute: 判断命令是否可执行的条件。
        private readonly Func<object, bool> _canExecute;

        // 构造函数：初始化命令的执行逻辑和可选的执行条件。
        public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
        {
            _execute = execute ?? throw new ArgumentNullException(nameof(execute));
            _canExecute = canExecute;
        }

        // CanExecuteChanged 事件：当命令可执行状态可能改变时触发，通知 UI 更新。
        // 绑定到 CommandManager.RequerySuggested，由 WPF 自动管理多数情况下的更新。
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        // CanExecute 方法：WPF 调用此方法来判断命令是否当前可以执行。
        public bool CanExecute(object parameter)
        {
            return _canExecute == null || _canExecute(parameter);
        }

        // Execute 方法：WPF 调用此方法来执行命令的实际操作。
        public void Execute(object parameter)
        {
            _execute(parameter);
        }
    }

    // RelayCommand<T> 类：泛型命令，用于指定特定参数类型的命令。
    // 提供类型安全的命令参数处理。
    public class RelayCommand<T> : ICommand
    {
        // _execute: 带泛型参数 T 的命令执行操作。
        private readonly Action<T> _execute;
        // _canExecute: 带泛型参数 T 的命令执行条件。
        private readonly Func<T, bool> _canExecute;

        // 构造函数：初始化带泛型参数的命令。
        public RelayCommand(Action<T> execute, Func<T, bool> canExecute = null)
        {
            _execute = execute ?? throw new ArgumentNullException(nameof(execute));
            _canExecute = canExecute;
        }

        // CanExecuteChanged 事件：与非泛型版本功能相同，通知 UI 更新命令状态。
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        // CanExecute 方法：判断命令是否可执行，并将传入参数转换为泛型类型 T。
        public bool CanExecute(object parameter)
        {
            return _canExecute == null || _canExecute((T)parameter);
        }

        // Execute 方法：执行命令操作，并将传入参数转换为泛型类型 T。
        public void Execute(object parameter)
        {
            _execute((T)parameter);
        }
    }
}